# _*_ coding:utf-8 _*_
# 开发团队: Mavericks
# 开发人员：Maverick·Ming
# 开发IDE： PyCharm
#   项目名：HelloWorld
#   文件名：5.06 作用域 命名空间.py
# 开发时间：2021/3/24 16:40

# 作用域 scope
# 作用域是指变量生效的区域
def fn():
    a = 10
    # print('局部变量 a = ', a, type(a))
    return


a = 'hello'
fn()
print('全局变量 a = ', a, type(a))


# 函数作用域：Python有两种作用域
# 全局作用域：函数内外任意位置均可读写，函数外的都是全局作用域，全局作用域中的变量称为全局变量
# 函数作用域：仅可函数内的位置读写，函数调用时创建，函数执行结束销毁，称为局部变量

# 变量的查找
#   - 当我们使用变量时，会优先在当前作用域中寻找变量，
#       如果有则使用，如果没有则继续到上一级作用域查找
#       直到在全局作用域中也没找到就会抛出异常

def fn2():
    # b = 10  # 在函数中给变量赋值，默认为局部变量赋值
    # 如果需要在函数内修改全局变量,则需要用global关键字提前声明变量
    global b
    b = 30
    print('局部b = ', b)


b = 20  # 全局变量b
fn2()
print('全局b = ', b)


# 命名空间 namespace
# 命名空间指的是，变量存储的位置，每一个变量都需要存储到指定的命名空间当中
# 每一个作用域都会有一个对应的命名空间
# 全局命名空间，用来保存全局变量。函数命名空间，用来保存函数中的变量。
# 命名空间实质上就是一字典，一个专门存储变量的字典

# locals() 用来获取当前作用域的命名空间
scope = locals()  # 返回当前命名空间（字典type）
print(scope, '\n', type(scope))
a = 50
print(a, type(a))
print(scope['a'], type(scope['a']))

# 向命名空间中添加一个key-value
scope['c'] = 20  # 向该字典中添加key-value，就相当于在当前作用域中声明了一个值为value的变量key
print(c, type(c))
# 一般不这么声明变量，麻烦，阅读性差，知道命名空间是字典即可


def scope_fn():
    a = 10
    scope = locals()  # 在函数内部调用locals()，只会获取函数作用域的命名空间
    scope['b1'] = 30  # 可以通过scope来操作函数的命名空间，不建议如此操作
    print(scope)
    print(scope['b1'])
    # print(b1)
    # 报错NameError: name 'b' is not defined

    # global()函数 可以用来在任意位置，获取全局命名空间
    global_scope = globals()
    print(global_scope)
    print(global_scope['a'])

scope_fn()
